using System;
using System.IO;

namespace OracleInternal.Network
{
	internal class AnoStream : Stream
	{
		private ITransportAdapter m_trns;

		private Stream m_strm;

		private SessionContext m_sess;

		private DataPacket m_wpac;

		private static byte[] Initial_Header = new byte[23]
		{
			0,
			154,
			0,
			0,
			6,
			0,
			0,
			0,
			0,
			0,
			222,
			173,
			190,
			239,
			0,
			144,
			0,
			0,
			0,
			0,
			0,
			1,
			0
		};

		private static int NS_HEADER_LEN = 10;

		private static int NS_HEADER_LEN_OFFSET = 0;

		private static int NA_HEADER_LEN_OFFSET = 14;

		private static int NA_HEADER_NMS_OFFSET = 20;

		private static int HEADER_TOT_OFFSET = 23;

		private static int FIRST_PACKET_SSPI_1ST_LEN_OFFSET = 91;

		private static int FIRST_PACKET_SSPI_2ND_LEN_OFFSET = 95;

		private static int SSPI_1ST_LEN_OFFSET = 35;

		private static int SSPI_2ND_LEN_OFFSET = 39;

		private static int SSPI_OFFSET = 43;

		private static int SSPI_LEN_SZ = 5;

		private static byte[] First_Packet = new byte[76]
		{
			0,
			1,
			0,
			7,
			0,
			0,
			0,
			0,
			0,
			4,
			0,
			5,
			2,
			0,
			0,
			0,
			0,
			4,
			0,
			4,
			0,
			0,
			0,
			9,
			0,
			4,
			0,
			4,
			0,
			0,
			0,
			2,
			0,
			20,
			0,
			1,
			2,
			0,
			0,
			0,
			4,
			0,
			0,
			0,
			2,
			0,
			0,
			0,
			0,
			0,
			0,
			0,
			0,
			0,
			0,
			0,
			0,
			4,
			0,
			1,
			0,
			0,
			0,
			0,
			0,
			4,
			0,
			1,
			55,
			0,
			0,
			0,
			0,
			55,
			0,
			1
		};

		private static byte[] Subsq_Packets = new byte[20]
		{
			0,
			1,
			0,
			2,
			0,
			0,
			0,
			0,
			0,
			4,
			0,
			1,
			55,
			0,
			0,
			0,
			0,
			55,
			0,
			1
		};

		private static byte[] Length_Packet = new byte[5]
		{
			22,
			1,
			0,
			0,
			0
		};

		private static byte[] EOF_Packet = new byte[5]
		{
			20,
			1,
			0,
			0,
			0
		};

		private byte[] what_is_this = new byte[5]
		{
			22,
			1,
			0,
			0,
			40
		};

		private int read_offset = SSPI_OFFSET;

		private int bytes_read;

		private int send_packet;

		private bool new_send = true;

		private bool neg_msg_sent;

		private bool auth_msg_sent;

		private int my_slough = 50;

		private int SSPI_Offset;

		private byte[] recv_buf;

		public override long Position
		{
			get
			{
				return m_strm.Position;
			}
			set
			{
				m_strm.Position = value;
			}
		}

		public override long Length => m_strm.Length;

		public override bool CanRead => m_strm.CanRead;

		public override bool CanSeek => m_strm.CanSeek;

		public override bool CanTimeout => m_strm.CanTimeout;

		public override bool CanWrite => m_strm.CanWrite;

		internal AnoStream(ITransportAdapter Trans, SessionContext SessCtx)
		{
			m_trns = Trans;
			m_strm = Trans.GetStream();
			m_sess = SessCtx;
			m_wpac = SessCtx.m_writerStream.m_dataPacket;
			recv_buf = new byte[SessCtx.m_sessionDataUnit + my_slough];
			send_packet = 1;
		}

		public override void Close()
		{
			m_strm.Close();
		}

		public new void Dispose()
		{
			m_strm.Dispose();
		}

		public override long Seek(long offset, SeekOrigin origin)
		{
			return m_strm.Seek(offset, origin);
		}

		public override void SetLength(long value)
		{
			m_strm.SetLength(value);
		}

		public override void Flush()
		{
			m_strm.Flush();
		}

		public override int Read(byte[] buffer, int offset, int count)
		{
			flush_write_data();
			if (bytes_read == 0)
			{
				if (count != Length_Packet.Length)
				{
					throw new NetworkException(-6328);
				}
				if (auth_msg_sent)
				{
					Array.Copy(EOF_Packet, 0, buffer, offset, count);
				}
				else
				{
					for (bytes_read = m_strm.Read(recv_buf, 0, NS_HEADER_LEN); bytes_read < NS_HEADER_LEN; bytes_read += m_strm.Read(recv_buf, bytes_read, NS_HEADER_LEN - bytes_read))
					{
					}
					int num;
					if (!m_sess.m_NSHandshakeComplete || m_sess.m_myversion < SessionContext.NSVSNLSD)
					{
						num = recv_buf[TNSPacketOffsets.NSPHDLEN] & 0xFF;
						num <<= 8;
						num |= recv_buf[TNSPacketOffsets.NSPHDLEN + 1] & 0xFF;
					}
					else
					{
						num = recv_buf[TNSPacketOffsets.NSPHDLEN] & 0xFF;
						num <<= 8;
						num |= recv_buf[TNSPacketOffsets.NSPHDLEN + 1] & 0xFF;
						num <<= 8;
						num |= recv_buf[TNSPacketOffsets.NSPHDLEN + 2] & 0xFF;
						num <<= 8;
						num |= recv_buf[TNSPacketOffsets.NSPHDLEN + 3] & 0xFF;
					}
					while (bytes_read < num)
					{
						bytes_read += m_strm.Read(recv_buf, bytes_read, recv_buf.Length - bytes_read);
					}
					read_offset = SSPI_OFFSET;
					if (bytes_read < SSPI_OFFSET)
					{
						throw new NetworkException(-6329);
					}
					int num2 = bytes_read - SSPI_OFFSET;
					Array.Copy(Length_Packet, 0, buffer, offset, 3);
					buffer[3 + offset] = (byte)((byte)(num2 / 256) & 0xFFu);
					buffer[4 + offset] = (byte)((byte)(num2 % 256) & 0xFFu);
				}
				return count;
			}
			int num3 = Math.Min(bytes_read - SSPI_OFFSET, count);
			Array.Copy(recv_buf, read_offset, buffer, offset, num3);
			read_offset += num3;
			if (read_offset >= bytes_read)
			{
				bytes_read = 0;
			}
			return num3;
		}

		public override int ReadByte()
		{
			return m_strm.ReadByte();
		}

		private void flush_write_data()
		{
			ushort num = (ushort)m_wpac.m_packetOffset;
			byte[] dataBuffer = m_wpac.m_dataBuffer;
			if (num > NS_HEADER_LEN)
			{
				DataPacket.InitForSend(dataBuffer, num, m_sess);
				dataBuffer[NA_HEADER_LEN_OFFSET] = (byte)((uint)((num - 10) / 256) & 0xFFu);
				dataBuffer[NA_HEADER_LEN_OFFSET + 1] = (byte)((uint)((num - 10) % 256) & 0xFFu);
				int num2 = SSPI_Offset - 8;
				int num3 = SSPI_Offset - 4;
				int num4 = num - SSPI_Offset;
				byte[] bytes = BitConverter.GetBytes(num4);
				for (int i = 0; i < 4; i++)
				{
					dataBuffer[num2 + i] = bytes[i];
				}
				dataBuffer[num3] = (byte)((byte)(num4 / 256) & 0xFFu);
				dataBuffer[num3 + 1] = (byte)((byte)(num4 % 256) & 0xFFu);
				m_wpac.Send(DataPacket.NSPDAFZER);
				send_packet++;
				new_send = true;
				if (!neg_msg_sent)
				{
					neg_msg_sent = true;
				}
				else if (!auth_msg_sent)
				{
					auth_msg_sent = true;
				}
			}
		}

		private void Process_write(byte[] buffer, int offset, int count)
		{
			bool flag = send_packet == 1;
			if (new_send)
			{
				new_send = false;
				byte[] array = (flag ? First_Packet : Subsq_Packets);
				if (!flag)
				{
					m_wpac.PutDataInBuffer(Initial_Header, NS_HEADER_LEN, Initial_Header.Length - NS_HEADER_LEN);
				}
				m_wpac.PutDataInBuffer(array, 0, array.Length);
				SSPI_Offset = m_wpac.m_packetOffset;
			}
			m_wpac.PutDataInBuffer(buffer, offset, count);
		}

		public override void Write(byte[] buffer, int offset, int count)
		{
			if (count != 5)
			{
				Process_write(buffer, offset, count);
			}
		}

		public override void WriteByte(byte value)
		{
			m_strm.WriteByte(value);
		}
	}
}
